
Imports System.ComponentModel

Namespace xpComponent.Form
    Public Class xpMenuItem
        Inherits System.Windows.Forms.MenuItem

        Private m_Image As System.Drawing.Image
        Private m_font As System.Drawing.Font
        Private w As Integer
        Private h As Integer

        Public Sub New()

            MyClass.New("", Nothing, Nothing, System.Windows.Forms.Shortcut.None)
        End Sub

        Public Sub New(ByVal text As String, ByVal image As System.Drawing.Image, ByVal onClick As EventHandler, ByVal shortcut As System.Windows.Forms.Shortcut)
            MyBase.New(text, onClick, shortcut)

            OwnerDraw = True
            m_Image = image
            m_font = System.Windows.Forms.SystemInformation.MenuFont
        End Sub

        <Category("Appearance"), DefaultValue(GetType(System.Drawing.Image), "None"), Description("The Image to be displayed in MenuItems Sidebar.")> _
        Public Property Image() As System.Drawing.Image
            Get
                Image = m_Image
            End Get
            Set(ByVal New_Image As System.Drawing.Image)
                m_Image = New_Image
            End Set
        End Property

        <Category("Appearance"), Description("The Font that displays in this MenuItem.")> _
        Public Property Font() As System.Drawing.Font
            Get
                Font = m_font
            End Get
            Set(ByVal New_Font As System.Drawing.Font)
                m_font = New_Font
            End Set
        End Property

        Private ReadOnly Property WindowMenu() As Boolean
            Get
                Return CBool(TypeOf (Me.Parent) Is System.Windows.Forms.MainMenu)
            End Get
        End Property

        Public ReadOnly Property Width() As Integer
            Get
                Return w
            End Get
        End Property

        Public ReadOnly Property Height() As Integer
            Get
                Return h
            End Get
        End Property

        Protected Overrides Sub OnMeasureItem(ByVal e As System.Windows.Forms.MeasureItemEventArgs)
            MyBase.OnMeasureItem(e)

            Dim ItemText As String
            Dim sf As New System.Drawing.StringFormat
            sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide

            'replace Chr(2) with two spaces to get overall text length.
            ItemText = JoinItemText().Replace(Chr(2), "  ")

            Select Case ItemText
                Case "-" 'Seperator
                    e.ItemHeight = 3
                Case Else
                    Dim szF As System.Drawing.SizeF
                    e.ItemHeight = CInt(e.Graphics.MeasureString(ItemText, m_font, szF, sf).Height)
                    If e.ItemHeight < 22 Then e.ItemHeight = 22
                    e.ItemWidth = CInt(e.Graphics.MeasureString(ItemText, m_font, szF, sf).Width) + 2
                    'If not TopLevel MenuItem then
                    If Not WindowMenu Then
                        e.ItemWidth += 44
                    End If
            End Select

            h = e.ItemHeight
            w = e.ItemWidth

            sf.Dispose()
        End Sub

        Protected Overrides Sub OnDrawItem(ByVal e As System.Windows.Forms.DrawItemEventArgs)
            MyBase.OnDrawItem(e)

            Dim SepLinePen As System.Drawing.Pen = System.Drawing.SystemPens.GrayText

            ClearBackGround(e)
            If WindowMenu Then
                DrawHiLite(e)
                DrawText(e)
            ElseIf Me.Text = "-" Then
                DrawSideBar(e)
                e.Graphics.DrawLine(SepLinePen, e.Bounds.X + 32, e.Bounds.Y + 1, e.Bounds.Right, e.Bounds.Y + 1)
            Else
                DrawSideBar(e)
                DrawHiLite(e)
                DrawText(e)
                'DrawImage
                If Not (m_Image Is Nothing) Then
                    'Create a 16 * 16 Bitmap from our Image.
                    Dim bmp As New System.Drawing.Bitmap(m_Image, 16, 16)
                    'Select the bottom left pixels color as the
                    'transparent color (as in Toolbar Bitmaps).
                    Dim TransColor As System.Drawing.Color = bmp.GetPixel(0, bmp.Height - 1)
                    bmp.MakeTransparent(TransColor)

                    If CBool(e.State And System.Windows.Forms.DrawItemState.Disabled) Then
                        'Draw the bitmap in a disabled state.
                        System.Windows.Forms.ControlPaint.DrawImageDisabled(e.Graphics, bmp, e.Bounds.X + 4, e.Bounds.Y + (e.Bounds.Height \ 2) - 8, System.Drawing.SystemColors.GrayText)
                    Else
                        If CBool(e.State And System.Windows.Forms.DrawItemState.Selected) Then
                            'copy the bitmap to act as shadow.
                            Dim bmpShadow As New System.Drawing.Bitmap(bmp)
                            Dim x As Integer, y As Integer

                            'Replace non transparent colors with
                            'ControlDarkDark Color.
                            For x = 0 To 15
                                For y = 0 To 15
                                    If bmpShadow.GetPixel(x, y).A <> 0 Then
                                        bmpShadow.SetPixel(x, y, System.Drawing.SystemColors.ControlDarkDark)
                                    End If
                                Next
                            Next

                            'draw Shadow.
                            e.Graphics.DrawImage(bmpShadow, New System.Drawing.Rectangle(e.Bounds.X + 5, e.Bounds.Y + (e.Bounds.Height \ 2) - 7, 16, 16), 0, 0, 16, 16, System.Drawing.GraphicsUnit.Pixel)
                            'draw bitmap.
                            e.Graphics.DrawImage(bmp, New System.Drawing.Rectangle(e.Bounds.X + 3, e.Bounds.Y + (e.Bounds.Height \ 2) - 9, 16, 16), 0, 0, 16, 16, System.Drawing.GraphicsUnit.Pixel)

                            'Finished with bmpShadow
                            bmpShadow.Dispose()

                        Else
                            'Draw bitmap.
                            e.Graphics.DrawImage(bmp, New System.Drawing.Rectangle(e.Bounds.X + 4, e.Bounds.Y + (e.Bounds.Height \ 2) - 8, 16, 16), 0, 0, 16, 16, System.Drawing.GraphicsUnit.Pixel)
                        End If
                    End If
                    'Finished with bmp.
                    bmp.Dispose()
                End If
            End If
        End Sub

        Private Sub ClearBackGround(ByVal e As System.Windows.Forms.DrawItemEventArgs)
            Dim BackBrush As System.Drawing.Brush = System.Drawing.SystemBrushes.Menu
            Dim BackRect As New System.Drawing.Rectangle(e.Bounds.X + 24, e.Bounds.Y, e.Bounds.Width - 24, e.Bounds.Height)

            If WindowMenu Then
                BackBrush = System.Drawing.SystemBrushes.Control
                BackRect.X -= 24
                BackRect.Width += 24
            End If

            e.Graphics.FillRectangle(BackBrush, BackRect)
        End Sub

        Private Sub DrawSideBar(ByVal e As System.Windows.Forms.DrawItemEventArgs)
            Dim SideBrush As System.Drawing.Brush = System.Drawing.SystemBrushes.Control
            e.Graphics.FillRectangle(SideBrush, New System.Drawing.Rectangle(e.Bounds.X, e.Bounds.Y, 24, e.Bounds.Height))
        End Sub

        Private Sub DrawHiLite(ByVal e As System.Windows.Forms.DrawItemEventArgs)
            'Dim HiLiteBrush As System.Drawing.Brush = System.Drawing.SystemBrushes.Highlight
            Dim HiLiteBrush As System.Drawing.Brush = System.Drawing.SystemBrushes.FromSystemColor(System.Drawing.SystemColors.InactiveCaptionText)
            'Dim HiLitePen As System.Drawing.Pen = System.Drawing.SystemPens.ControlDark
            Dim HiLitePen As System.Drawing.Pen = System.Drawing.SystemPens.Highlight

            If Not CBool(e.State And System.Windows.Forms.DrawItemState.Disabled) Then
                If CBool(e.State And System.Windows.Forms.DrawItemState.Selected) _
                Or CBool(e.State And System.Windows.Forms.DrawItemState.HotLight) Then
                    e.Graphics.FillRectangle(HiLiteBrush, New System.Drawing.Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, e.Bounds.Height))
                    e.Graphics.DrawRectangle(HiLitePen, New System.Drawing.Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1))
                End If
            End If
        End Sub

        Private Sub DrawText(ByVal e As System.Windows.Forms.DrawItemEventArgs)
            Dim TextRectF As New System.Drawing.RectangleF(e.Bounds.X + 32, e.Bounds.Top, e.Bounds.Width - 48, e.Bounds.Height)
            Dim TextBrush As System.Drawing.Brush = System.Drawing.SystemBrushes.ControlText
            Dim sItemText() As String = Split(JoinItemText(), Chr(2))
            Dim sf As New System.Drawing.StringFormat(System.Drawing.StringFormatFlags.NoWrap)

            'Vertical Centre Align for Text.
            sf.LineAlignment = System.Drawing.StringAlignment.Center
            'Show Hot-Key UnderScore in Text.
            sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show

            If WindowMenu Then
                TextRectF = New System.Drawing.RectangleF(e.Bounds.X + 8, e.Bounds.Y, e.Bounds.Width - 8, e.Bounds.Height)
            End If

            If CBool(e.State And System.Windows.Forms.DrawItemState.Selected) _
            Or CBool(e.State And System.Windows.Forms.DrawItemState.HotLight) Then
                TextBrush = System.Drawing.SystemBrushes.WindowText
            End If

            If CBool(e.State And System.Windows.Forms.DrawItemState.Disabled) Then
                TextBrush = System.Drawing.SystemBrushes.FromSystemColor(System.Drawing.SystemColors.GrayText)
            End If

            e.Graphics.DrawString(sItemText(0), m_font, TextBrush, TextRectF, sf)
            'If ControlKey present then...
            If UBound(sItemText) = 1 Then
                'Right Align for Control Key Text.
                sf.Alignment = System.Drawing.StringAlignment.Far
                e.Graphics.DrawString(sItemText(1), m_font, TextBrush, TextRectF, sf)
            End If

            'Finished with StringFormat and sItemText.
            sf.Dispose()
            Erase sItemText
        End Sub

        Private Function JoinItemText() As String
            Dim ItemText As String = Me.Text

            If Me.ShowShortcut And Me.Shortcut <> Shortcut.None Then
                Dim k As System.Windows.Forms.Keys = CType(Me.Shortcut, System.Windows.Forms.Keys)
                ItemText += Chr(2) & TypeDescriptor.GetConverter(GetType(System.Windows.Forms.Keys)).ConvertToString(k)
            End If

            Return ItemText
        End Function

        Private Sub InitializeComponent()
        End Sub
    End Class
End Namespace